#include "src\precompiled.h"
#include "src\animation.h"
#include "src\skeleton.h"

joint::joint(size_t id)
	:	m_scale(vector3(1.0f, 1.0f, 1.0f)),
		m_orientation(quaternion(1.0f, 0.0f, 0.0f, 0.0f)),
		m_id(id),
		m_parent(0)
{ }

joint::~joint() { }

void joint::set_name(const std::string &name) { m_name = name; }

void joint::set_transforms(const matrix4 &tm) { tm.decomposition(m_position, m_scale, m_orientation); }

void joint::set_position(const vector3 &position) { m_position = position; }

void joint::set_orientation(const quaternion &orientation) { m_orientation = orientation; }

void joint::set_scale(const vector3 &scale) { m_scale = scale; }

void joint::set_parent(joint *parent) { m_parent = parent; }

size_t joint::add_child(joint *child)
{
	size_t id = m_childs.size();
	m_childs.push_back(child);
	child->set_parent(this);
	return id;
}

void joint::remove_child(size_t id)
{
	joint *child = get_child(id);
	child->set_parent(0);
	m_childs.erase(m_childs.begin() + id);
}

size_t joint::get_num_childs() const { return m_childs.size(); }

joint *joint::get_child(size_t id) const { return m_childs[id]; }

joint *joint::get_parent() const { return m_parent; }

joint *joint::get_root() const
{
	joint *_this = const_cast<joint*>(this);
	joint *parent = m_parent;
	while(parent != 0) {
		_this = parent;
		parent = parent->get_parent();
	}
	return _this;
}

size_t joint::get_id() const { return m_id; }

vector3 joint::get_position() const { return m_position; }

quaternion joint::get_orientation() const { return m_orientation; }

vector3 joint::get_scale() const { return m_scale; }

std::string joint::get_name() const { return m_name; }

//-----------------------------------------------------------------------------

skeleton::skeleton() { }

skeleton::~skeleton() { }

void skeleton::set_name(const std::string &name) { m_name = name; }

void skeleton::set_animation(animation_ptr anim) { m_animation = anim; }

void skeleton::clear()
{
	m_name.clear();
	m_animation.release();
	m_joints.clear();
}

joint_ptr skeleton::create_joint(size_t id)
{
	joint_ptr temp(new joint(id));
	m_joints.push_back(temp);
	return temp;
}

std::string skeleton::get_name() const { return m_name; }

animation_ptr skeleton::get_animation() const { return m_animation; }

size_t skeleton::get_num_joints() const { return m_joints.size(); }

joint_ptr skeleton::get_joint_by_id(size_t id)
{
	for(size_t i = 0; i < m_joints.size(); i++) {
		joint_ptr jnt = m_joints[i];
		if(jnt->get_id() == id)
			return jnt;
	}
	return joint_ptr();
}

joint_ptr skeleton::get_joint_by_handle(size_t h) { return m_joints[h]; }

skeleton::joint_vec skeleton::build_hierarchy() const
{
	std::set<joint*> joints;
	for(size_t i = 0; i < m_joints.size(); i++)
		joints.insert(m_joints[i]->get_root());
	return joint_vec(joints.begin(), joints.end());
}